home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 October: Mac OS SDK / Dev.CD Oct 00 SDK1.toast / Development Kits / Mac OS / Multiprocessing 2.1v2 SDK / Sample Code / MP Sort Picts 12⁄04⁄99 / CopyBlits Folder / MPCopyBlits.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-04  |  10.5 KB  |  440 lines  |  [TEXT/CWIE]

  1. /*  CopyBlits
  2.  
  3. File name: CopyBlits.c
  4. Function: Optimized CopyBits
  5. History:    5/26/94 Original by George A. Warner
  6. History:    10/7/98 Interlace code written
  7. History        11/2/98 Added MP support mxmora@best.com
  8.  
  9. */
  10.  
  11. #define DO_LOCKING 0
  12.  
  13. #include "MPCopyBlits.h"
  14.  
  15. #include "MPBlitter.h"
  16.  
  17.  
  18. static CTabHandle gCTabHandle = nil;
  19. static UInt16 gCTab16[256];
  20. static UInt32 gCTab32[256];
  21.  
  22. // implementation
  23. void Set_ColorTable(CTabHandle pCTabHandle)
  24. {
  25.     if (gCTabHandle != pCTabHandle)
  26.     {
  27.         gCTabHandle = pCTabHandle;
  28.         if (pCTabHandle)
  29.         {
  30.             if ((*pCTabHandle)->ctSize >= 255)
  31.             {
  32.                 short index;
  33.                 for (index = 0;index < 256;index++)
  34.                 {
  35.                     RGBColor tRGBColor = (**pCTabHandle).ctTable[index].rgb;
  36.                     gCTab32[index] =     ((tRGBColor.red >> 8) << 16) +
  37.                                         ((tRGBColor.green >> 8) << 8) +
  38.                                         ((tRGBColor.blue >> 8) << 0);
  39.                     gCTab16[index] =     ((tRGBColor.red >> 11) << 10) +
  40.                                         ((tRGBColor.green >> 11) << 5) +
  41.                                         ((tRGBColor.blue >> 11) << 0);
  42.                 }
  43.             }
  44.         }
  45.     }
  46. }
  47.  
  48. // Generic routine that uses pixel size to determ which optimized routine to use
  49. // If you KNOW your depth you should call the approate routine yourself and skip
  50. // the subroutine/switch overhead.
  51.  
  52. void CopyBlits    (    const PixMapHandle srcPixMapHdl,
  53.                         const PixMapHandle dstPixMapHdl,
  54.                         const Rect *srcRect,
  55.                         const Rect *dstRect,
  56.                         MPCriticalRegionID busy
  57. )
  58. {
  59.     if ((*srcPixMapHdl)->pixelSize == 8)
  60.     {
  61.         switch ((*dstPixMapHdl)->pixelSize)
  62.         {
  63.             case    8:
  64. //                CopyBlits8(srcPixMapHdl,dstPixMapHdl,srcRect,dstRect);
  65.                 CopyBlits8_8(srcPixMapHdl,dstPixMapHdl,srcRect,dstRect,busy);
  66.                 break;
  67.             case    16:
  68.                 CopyBlits8_16(srcPixMapHdl,dstPixMapHdl,srcRect,dstRect,busy);
  69.                 break;
  70.             case    32:
  71.                 CopyBlits8_32(srcPixMapHdl,dstPixMapHdl,srcRect,dstRect,busy);
  72.                 break;
  73.             default:
  74.                 //
  75.                 MPCopyBits((BitMap*) *srcPixMapHdl,(BitMap*) *dstPixMapHdl,srcRect,dstRect,0,(RgnHandle) busy);
  76.                 break;
  77.         }
  78.     }
  79.     else
  80.     {
  81.         // schedult one via RPC
  82.         MPCopyBits((BitMap*) *srcPixMapHdl,(BitMap*) *dstPixMapHdl,srcRect,dstRect,0,(RgnHandle)busy);
  83.     }
  84. }
  85.  
  86.  
  87. // This is one of the first non-asm blitters I ever saw. Not as fast as CopyBlits8_8 but I left
  88. // it in just to show you the skanky nested switch/while code (see Duff's device). ewueee!
  89.  
  90. // 194 fps vs. 300 fps CopyBits
  91. static void CopyBlits8    (    const PixMapHandle srcPixMapHdl,
  92.                     const PixMapHandle dstPixMapHdl,
  93.                     const Rect *srcRect,
  94.                     const Rect *dstRect
  95. )
  96. {
  97.     long            dstLeft,dstRight;
  98.     long            *srcRow,*dstRow;
  99.     register long    *srcPtr,*dstPtr;
  100.     long            leftMask,rightMask;
  101.     long            notLeftMask,notRightMask;
  102.  
  103.     long            srcRowBytes;
  104.     long            dstRowBytes;
  105.     long            srcLeft;
  106.  
  107.     long            dstLong;
  108.     short            dstLongs;
  109.     short            height;
  110.     long            offset;
  111.     long            timesCopy;
  112.  
  113.     // This assumes that the pixmap is already locked
  114.     srcRow = (long *) (*srcPixMapHdl)->baseAddr;
  115.     dstRow = (long *) (*dstPixMapHdl)->baseAddr;
  116.     
  117.     // get the bit offset to the src left edge
  118.     srcLeft = (srcRect->left - (*srcPixMapHdl)->bounds.left) * (*srcPixMapHdl)->pixelSize;
  119.         
  120.     // offset the src ptr to the first long
  121.     srcRow += srcLeft >> 5;
  122.     
  123.     // get the bit offset to the dst left and right edges
  124.     dstLeft = (dstRect->left - (*dstPixMapHdl)->bounds.left) * (*dstPixMapHdl)->pixelSize;
  125.     dstRight = (dstRect->right - (*dstPixMapHdl)->bounds.left) * (*dstPixMapHdl)->pixelSize;
  126.     
  127.     // get the number of middle longs to do minus the left edge long
  128.     dstLongs = ((dstRight - dstLeft) >> 5) - 1;
  129.     
  130.     // offset the dst Ptr to the first long
  131.     dstRow += dstLeft >> 5;
  132.  
  133.     // now compute left and right masks for the dst
  134.     dstLeft &= 0x1f;
  135.     leftMask = ( 1 << dstLeft ) - 1;
  136.     notLeftMask = ~leftMask;
  137.     
  138.     dstRight &= 0x1f;
  139.     notRightMask = ( 1 << dstRight ) - 1;
  140.     rightMask = ~notRightMask;
  141.     
  142.     srcRowBytes = (*srcPixMapHdl)->rowBytes & 0x3fff;
  143.     dstRowBytes = (*dstPixMapHdl)->rowBytes & 0x3fff;
  144.  
  145.     // offset the src and dst ptrs to the first row
  146.     offset = (srcRect->top - (*srcPixMapHdl)->bounds.top) * srcRowBytes;
  147.     srcRow = (long*) ((Ptr) srcRow + offset);
  148.  
  149.     offset = (dstRect->top - (*dstPixMapHdl)->bounds.top) * dstRowBytes;
  150.     dstRow = (long*) ((Ptr) dstRow + offset);
  151.  
  152.     /* check if we need to do the left and right mask */
  153.     if ( leftMask )
  154.     {
  155.         if ( notLeftMask == 0 )
  156.         {
  157.             leftMask = 0;
  158.             dstLongs++;
  159.         }
  160.     }
  161.         
  162.     if ( rightMask )
  163.     {
  164.         if ( notRightMask == 0 )
  165.         {
  166.             rightMask = 0;
  167.             dstLongs++;
  168.         }
  169.     }
  170.  
  171.     height = srcRect->bottom - srcRect->top;    // No scaling allowed
  172.  
  173.     //for ( ; height >= 0; --height )
  174.     // changing the above 'for()' to the below 'while()' is what made this blit routine
  175.     // faster than CopyBits - a speed improvement equal to all other changes I had made
  176.     // previously.  (about 4 to 5 milliseconds, in case you were wondering)
  177.     // Lesson: the true bottlenecks are not always the obvious ones
  178.     while (height--)
  179.     {
  180.         srcPtr = srcRow;
  181.         dstPtr = dstRow;
  182.         
  183.         /* do the masked left edge */
  184.         if ( leftMask )
  185.         {
  186.             dstLong = *srcPtr++ & leftMask;
  187.             dstLong |= *dstPtr & notLeftMask;
  188.             *dstPtr++ = dstLong;
  189.         }
  190.  
  191.         /* do the middle longs with Duff's device */
  192.         timesCopy = (dstLongs + 15) >> 4;
  193.         
  194.         switch( dstLongs & 0xF )
  195.         {
  196.             case 0:    do
  197.                 {    *dstPtr++ = *srcPtr++;
  198.             case 15:    *dstPtr++ = *srcPtr++;
  199.             case 14:    *dstPtr++ = *srcPtr++;
  200.             case 13:    *dstPtr++ = *srcPtr++;
  201.             case 12:    *dstPtr++ = *srcPtr++;
  202.             case 11:    *dstPtr++ = *srcPtr++;
  203.             case 10:    *dstPtr++ = *srcPtr++;
  204.             case 9:        *dstPtr++ = *srcPtr++;
  205.             case 8:        *dstPtr++ = *srcPtr++;
  206.             case 7:        *dstPtr++ = *srcPtr++;
  207.             case 6:        *dstPtr++ = *srcPtr++;
  208.             case 5:        *dstPtr++ = *srcPtr++;
  209.             case 4:        *dstPtr++ = *srcPtr++;
  210.             case 3:        *dstPtr++ = *srcPtr++;
  211.             case 2:        *dstPtr++ = *srcPtr++;
  212.             case 1:        *dstPtr++ = *srcPtr++;
  213.                 } while( --timesCopy > 0 );
  214.         }
  215.  
  216.         /* do the masked right edge */
  217.         if ( rightMask )
  218.         {
  219.             dstLong = *srcPtr & rightMask;
  220.             dstLong |= *dstPtr & notRightMask;
  221.             *dstPtr = dstLong;
  222.         }
  223.         
  224.         /* bump to the next row */
  225.         srcRow = (long*) ((Ptr) srcRow + srcRowBytes);
  226.         dstRow = (long*) ((Ptr) dstRow + dstRowBytes);
  227.     }
  228. }
  229.  
  230. inline UInt8 * MyGetPixBaseAddr(PixMapHandle pixMap)
  231. {
  232.     return (UInt8*)pixMap[0]->baseAddr;
  233. }
  234.  
  235. // my Fastest (non-asm) 8 to 8 bit blitter
  236.  
  237. // 354 fps vs. 300 fps CopyBits
  238. void CopyBlits8_8    (    const PixMapHandle srcPixMapHdl,
  239.                         const PixMapHandle dstPixMapHdl,
  240.                         const Rect *srcRect,
  241.                         const Rect *dstRect,
  242.                         MPCriticalRegionID blitterBusy)
  243. {
  244.     UInt32    doubleCount,lineCount,count;
  245.     UInt8    startFlags, endFlags;
  246.     UInt8    *src, *dst;
  247.     UInt32    srcSkip, dstSkip;
  248.     UInt32    width,height;
  249.  
  250.     (void) MPEnterCriticalRegion(blitterBusy, kDurationForever);
  251.  
  252.     width = srcRect->right - srcRect->left;
  253.     height = srcRect->bottom - srcRect->top;
  254.  
  255.     if (!width || !height)
  256.     {
  257.         goto exit;
  258.     }
  259.     
  260.     srcSkip = (*srcPixMapHdl)->rowBytes & 0x3FFF;
  261.     dstSkip = (*dstPixMapHdl)->rowBytes & 0x3FFF;
  262.  
  263.     src = (UInt8*) MyGetPixBaseAddr(srcPixMapHdl) +
  264.         (srcSkip * (srcRect->top - (*srcPixMapHdl)->bounds.top)) +
  265.         srcRect->left - (*srcPixMapHdl)->bounds.left;
  266.     dst = (UInt8*) MyGetPixBaseAddr(dstPixMapHdl) +
  267.         (dstSkip * (dstRect->top - (*dstPixMapHdl)->bounds.top)) +
  268.         dstRect->left - (*dstPixMapHdl)->bounds.left;
  269.  
  270.     startFlags = ((UInt8 *) (((UInt32) src + 7U) & ~7U)) - src;
  271.     endFlags = ((UInt32) (src + width)) & 7U;
  272.     doubleCount = ((width - startFlags) - endFlags) / 8;
  273.  
  274.     // pre-fix skip values
  275.     srcSkip -= width;
  276.     dstSkip -= width;
  277.     
  278.     for (lineCount = 0; lineCount < height; lineCount++)
  279.     {
  280.         if (startFlags & 1)    // byte align
  281.             *dst++ = *src++;
  282.  
  283.         if (startFlags & 2)    // word align
  284.         {
  285.             *(UInt16*) dst = *(UInt16*) src;
  286.             src += 2;
  287.             dst += 2;
  288.         }
  289.  
  290.         if (startFlags & 4)    // long align
  291.         {
  292.             *(UInt32*) dst = *(UInt32*) src;
  293.             src += 4;
  294.             dst += 4;
  295.         }
  296.  
  297.         // copy doubles
  298.         for (count = 0; count < doubleCount; count++)
  299.         {
  300.             *(double*) dst = *(double*) src;
  301.             src += 8;
  302.             dst += 8;
  303.         }
  304.  
  305.         // copy remaining long
  306.         if (endFlags & 4)
  307.         {
  308.             *(UInt32*) dst = *(UInt32*) src;
  309.             src += 4;
  310.             dst += 4;
  311.         }
  312.             
  313.         // copy remaining word
  314.         if (endFlags & 2)
  315.         {
  316.             *(UInt16*) dst = *(UInt16*) src;
  317.             src += 2;
  318.             dst += 2;
  319.         }
  320.  
  321.         // copy remaining byte
  322.         if (endFlags & 1)
  323.             *dst++ = *src++;
  324.  
  325.         src += srcSkip;
  326.         dst += dstSkip;
  327.     }
  328.  
  329. exit:
  330.     (void)MPExitCriticalRegion(blitterBusy);
  331. }
  332.  
  333. // my Fastest (non-asm) 8 to 16 bit blitter
  334.  
  335. // 50 fps vs. 42 fps CopyBits
  336. void CopyBlits8_16    (    const PixMapHandle srcPixMapHdl,
  337.                         const PixMapHandle dstPixMapHdl,
  338.                         const Rect *srcRect,
  339.                         const Rect *dstRect,
  340.                         MPCriticalRegionID blitterBusy
  341. )
  342. {
  343.     UInt32    count;
  344.     UInt8    *src;
  345.     UInt16    *dst;
  346.     UInt32    srcSkip, dstSkip;
  347.     UInt32    width,height;
  348.  
  349.     (void)MPEnterCriticalRegion(blitterBusy, kDurationForever);
  350.  
  351.     Set_ColorTable((**srcPixMapHdl).pmTable);
  352.  
  353.     width = srcRect->right - srcRect->left;
  354.     height = srcRect->bottom - srcRect->top;
  355.  
  356.     if (!width || !height)
  357.     {
  358.         goto exit;
  359.     }
  360.  
  361.     srcSkip = (*srcPixMapHdl)->rowBytes & 0x3FFF;
  362.     dstSkip = (*dstPixMapHdl)->rowBytes & 0x3FFF;
  363.  
  364.     src = (UInt8*) (MyGetPixBaseAddr(srcPixMapHdl) +
  365.         (srcSkip * (srcRect->top - (*srcPixMapHdl)->bounds.top)) +
  366.         srcRect->left - (*srcPixMapHdl)->bounds.left);
  367.     dst = (UInt16*) (MyGetPixBaseAddr(dstPixMapHdl) +
  368.         (dstSkip * (dstRect->top - (*dstPixMapHdl)->bounds.top)) +
  369.         ((dstRect->left - (*dstPixMapHdl)->bounds.left) << 1));
  370.  
  371.     // pre-fix skip values
  372.     srcSkip -= width;
  373.     dstSkip -= width << 1;
  374.  
  375.     while (height--)
  376.     {
  377.         for (count = 0; count < width; count++)
  378.             *dst++ = gCTab16[*src++];
  379.         src += srcSkip;
  380.         dst = (UInt16*) (dstSkip + (Ptr) dst);
  381.     }
  382.  
  383. exit:
  384.     (void)MPExitCriticalRegion(blitterBusy);
  385.  
  386. }
  387.  
  388. // my Fastest (non-asm) 8 to 32 bit blitter
  389.  
  390. // 50 fps vs. 39 fps CopyBits
  391. void CopyBlits8_32    (    const PixMapHandle srcPixMapHdl,
  392.                         const PixMapHandle dstPixMapHdl,
  393.                         const Rect *srcRect,
  394.                         const Rect *dstRect,
  395.                         MPCriticalRegionID blitterBusy
  396. )
  397. {
  398.     register    UInt32    count;
  399.     register    UInt8    *src;
  400.     register    UInt32    *dst;
  401.     register    UInt32    srcSkip, dstSkip;
  402.     register    UInt32    width,height;
  403.  
  404.     (void) MPEnterCriticalRegion(blitterBusy, kDurationForever);
  405.  
  406.     Set_ColorTable((**srcPixMapHdl).pmTable);
  407.  
  408.     width = srcRect->right - srcRect->left;
  409.     height = srcRect->bottom - srcRect->top;
  410.  
  411.     if (!width || !height)
  412.     {
  413.         goto exit;
  414.     }
  415.     srcSkip = (*srcPixMapHdl)->rowBytes & 0x3FFF;
  416.     dstSkip = (*dstPixMapHdl)->rowBytes & 0x3FFF;
  417.  
  418.     src = (UInt8*) (MyGetPixBaseAddr(srcPixMapHdl) +
  419.         (srcSkip * (srcRect->top - (*srcPixMapHdl)->bounds.top)) +
  420.         srcRect->left - (*srcPixMapHdl)->bounds.left);
  421.     dst = (UInt32*) (MyGetPixBaseAddr(dstPixMapHdl) +
  422.         (dstSkip * (dstRect->top - (*dstPixMapHdl)->bounds.top)) +
  423.         ((dstRect->left - (*dstPixMapHdl)->bounds.left) << 2));
  424.  
  425.     // pre-fix skip values
  426.     srcSkip -= width;
  427.     dstSkip -= width << 2;
  428.  
  429.     while (height--)
  430.     {
  431.         for (count = 0; count < width; count++)
  432.             *dst++ = gCTab32[*src++];
  433.         src += srcSkip;
  434.         dst = (UInt32*) (dstSkip + (Ptr) dst);
  435.     }
  436.  
  437. exit:
  438.     (void) MPExitCriticalRegion(blitterBusy);
  439. }
  440.